package com.weijian.demo1.controller;

import com.weijian.demo1.model.DocumentEditMessage;
import com.weijian.demo1.service.DocumentDebounceService;
import com.weijian.demo1.service.DocumentMemoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

/**
 * 文档实时协作WebSocket控制器
 * 处理文档的实时编辑、保存、光标位置等WebSocket消息
 * 基于STOMP协议实现实时通信
 */
@Controller
@Tag(name = "文档实时协作", description = "处理文档的实时编辑、保存、光标位置等WebSocket消息，基于STOMP协议实现实时通信")
public class DocumentWebSocketController {

    private final DocumentMemoryService documentMemoryService;
    private final DocumentDebounceService documentDebounceService;

    public DocumentWebSocketController(DocumentMemoryService documentMemoryService,
                                       DocumentDebounceService documentDebounceService) {
        this.documentMemoryService = documentMemoryService;
        this.documentDebounceService = documentDebounceService;
    }

    /**
     * 处理实时文档编辑消息
     * WebSocket端点：/app/document/{documentId}/edit
     * 广播地址：/topic/document/{documentId}
     * 
     * @param documentId 文档ID
     * @param message 编辑消息（包含用户ID、编辑内容、光标位置等）
     * @return 处理后的编辑消息，广播给所有在线用户
     * @throws Exception 处理过程中可能发生的异常
     * @apiNote 
     * - 实时更新内存缓存，实现毫秒级同步
     * - 触发2秒防抖机制，延迟保存到数据库
     * - 自动增加版本号防止编辑冲突
     * - 不直接保存到数据库，确保实时性能
     */
    @MessageMapping("/document/{documentId}/edit")
    @SendTo("/topic/document/{documentId}")
    @Operation(summary = "处理实时文档编辑消息", description = "处理文档的实时编辑消息，实时更新内存缓存，触发2秒防抖机制延迟保存到数据库")
    public DocumentEditMessage handleDocumentEdit(
            @DestinationVariable @Parameter(description = "文档ID") Long documentId,
            DocumentEditMessage message) throws Exception {

        // 增加版本号防止冲突
        long version = System.currentTimeMillis();
        message.setVersion(version);

        // 1. 先更新到内存缓存（实时同步）
        documentMemoryService.updateInMemory(documentId, message.getContent());

        // 2. 触发防抖保存（2秒后异步保存到数据库）
        documentDebounceService.debounceSave(documentId, message.getUserId());

        // 3. 实时编辑消息，不保存到数据库，仅广播给所有用户
        message.setTimestamp(java.time.LocalDateTime.now());
        return message;
    }

    /**
     * 处理用户主动保存文档消息
     * WebSocket端点：/app/document/{documentId}/save
     * 广播地址：/topic/document/{documentId}/saved
     * 
     * @param documentId 文档ID
     * @param message 保存消息（包含用户ID、保存内容等）
     * @return 保存确认消息，广播给发起保存的用户
     * @throws Exception 保存过程中可能发生的异常
     * @apiNote 
     * - 立即保存文档内容到数据库
     * - 取消防抖保存任务，避免重复保存
     * - 从内存获取最新内容确保数据一致性
     * - 设置消息类型为"SAVED"标识主动保存
     */
    @MessageMapping("/document/{documentId}/save")
    @SendTo("/topic/document/{documentId}/saved")
    @Operation(summary = "处理用户主动保存文档消息", description = "处理用户主动保存文档的请求，立即保存文档内容到数据库并取消防抖保存任务")
    public DocumentEditMessage handleDocumentSave(
            @DestinationVariable @Parameter(description = "文档ID") Long documentId,
            DocumentEditMessage message) throws Exception {

        // 用户主动保存：立即保存并取消防抖任务
        documentDebounceService.immediateSave(documentId, message.getUserId());

        // 从内存获取最新内容
        String latestContent = documentMemoryService.getFromMemory(documentId);
        if (latestContent != null) {
            message.setContent(latestContent);
        }

        message.setTimestamp(java.time.LocalDateTime.now());
        message.setType("SAVED");
        return message;
    }

    /**
     * 处理光标位置更新消息
     * WebSocket端点：/app/document/{documentId}/cursor
     * 广播地址：/topic/document/{documentId}/cursor
     * 
     * @param documentId 文档ID
     * @param message 光标位置消息（包含用户ID、光标位置、用户标识等）
     * @return 光标位置消息，广播给所有在线用户
     * @apiNote 
     * - 实时同步用户光标位置，提升协作体验
     * - 不保存任何数据，纯实时展示功能
     * - 可用于显示其他用户正在编辑的位置
     */
    @MessageMapping("/document/{documentId}/cursor")
    @SendTo("/topic/document/{documentId}/cursor")
    @Operation(summary = "处理光标位置更新消息", description = "处理用户光标位置更新消息，实时同步用户光标位置，提升协作体验")
    public DocumentEditMessage handleCursorPosition(
            @DestinationVariable @Parameter(description = "文档ID") Long documentId,
            DocumentEditMessage message) {

        message.setTimestamp(java.time.LocalDateTime.now());
        return message;
    }
}